from hruntools.parser.parservisitor.visitorbase import Element, Visitor
from hruntools.parser.parservisitor.visitorlines import LinesVisitor

# 字段名与 字段类型的对应关系
# Field_dict = ['variables', 'parameters', 'request.params', 'request.data']
# Field_dictStr = ['request.headers', 'headers']
# Field_list = ['extract', 'validate']
# Field_json = ['request.json']
# Field_bool = ['verify', 'skiped', 'skip']
# Field_array = ['output']
# Field_string = []
# Field_sheet = ['testcase']

typeMapping = {
    'dict': ['variables', 'parameters', 'request.params', 'request.data'],
    'dictstr': ['request.headers', 'headers'],
    'list': ['extract', 'validate'],
    'json': ['request.json'],
    'bool': ['verify'],
    'skip': ['skiped', 'skip'],
    'array': ['output'],
    'string': [],
    'sheet': ['testcase'],
}


class Field(Element):
    def __init__(self, index, value, name=''):
        self.index = index
        self.name = name
        self.value = value

    def to_dict(self):
        # todo
        # if self.name.startswith('request'):
        #     if 'request' not in ret:
        #         ret['request'] = {}
        #
        #     ret['request'][f[8:]] = self.rowList[id].value
        # else:
        #     ret[f] = self.rowList[id].value

        return {self.name: self._value}

    def __str__(self):
        return str(self.name)

    @property
    def value(self):
        return self._value

    @value.setter
    def value(self, value):
        self._value = value

    @property
    def type(self):
        for k, v in typeMapping.items():
            if self.name in v:
                return k
        return 'string'

    # @override
    def accept(self, v, retdict):
        return v.visit(self, retdict)


class FieldVisitor(Visitor):  # , FieldMixin):

    # def get_meth_name(self, element):
    #     def checkType():
    #         for k, v in typeMapping.items():
    #             if element.name in v:
    #                 return k
    #         return 'string'
    #
    #     return 'parser_' + checkType()
    #
    # def parser_string(self, element):
    #     return str(element.value)
    #
    # def parser_dict(self, element):
    #     return self.parserValueToDict(element.value)
    #
    # def parser_dictstr(self, element):
    #     # 值为 string 类型
    #     return self.parserValueToDict(element.value, value2string=True)
    #
    # def parser_list(self, element):
    #     # list格式类型
    #     return self.parserValue2List(element.value)
    #
    # def parser_json(self, element):
    #     # json 兼容
    #     if element.value.startswith('{'):
    #         return eval(element.value)
    #
    #     return self.parser_dict(element)
    #
    # def parser_bool(self, element):
    #     # 解析verify false\true
    #     return False if element.value == 0 else True
    #
    # def parser_array(self, element):
    #     return self.parserValue2ArrayList(element.value)
    #
    # def parser_sheet(self, element):
    #     pass

    def getValue(self, field):
        # def isType(xtype):
        #     return field.name in xtype
        #
        # def checkType():
        #     for k, v in typeMapping.items():
        #         if field.name in v:
        #             return k
        #     return 'string'

        return LinesVisitor(field).visit()

        # return self.visitByName(field)

        # ret = field.value
        # fieldType = checkType()
        #
        # if isType(Field_json):
        #     # json 兼容
        #     if field.value.startswith('{'):
        #         ret = eval(ret)
        #     else:
        #         ret = self.parserValueToDict(ret)
        #
        # elif isType(Field_dictStr):
        #     # 值为 string 类型
        #     ret = self.parserValueToDict(ret, value2string=True)
        #
        # elif isType(Field_dict):
        #     ret = self.parserValueToDict(ret)
        #
        # elif isType(Field_list):
        #     # list格式类型
        #     ret = self.parserValue2List(ret)
        #
        # elif isType(Field_array):
        #     ret = self.parserValue2ArrayList(ret)
        #
        # elif isType(Field_bool):
        #     # 解析verify false\true
        #     ret = False if ret == 0 else True
        #
        # return ret

    def visit(self, field, retdict={}):
        return self.toDict(field, retdict)

    def toDict(self, field, retdict={}):
        if field.value == "":
            return retdict
        if field.name.startswith('request'):
            if 'request' not in retdict:
                retdict['request'] = {}

            retdict['request'][field.name[8:]] = self.getValue(field)
        elif field.name.startswith('testcase'):
            retdict['testcase_def'] = self.getValue(field)
        else:
            retdict[field.name] = self.getValue(field)
        return retdict


class Record(Element):
    def __init__(self, index, row, fieldRec=None):
        # if len(row) == 0: return
        self.index = index
        self.valueList = None
        self.fieldList = fieldRec

        self.row = row

        self.setFieldRow(fieldRec)

        # self.createField(row)

    def __str__(self):
        return str(self.row)

    def __getitem__(self, index):
        if self.valueList is None:  # 如果是字段名行， valuelist 值列标会为None
            return self.row[index]
        else:
            return self.valueList[index]
        # if self.type in ['configLine', 'teststepsLine', 'testcasesLine', 'FieldsLine']:
        #     return self.row[index]
        # else:
        #     return self.valueList[index]

    @property
    def isSkip(self):

        return False

    def setFieldRow(self, fieldrow):
        self.fieldList = fieldrow
        self.create_record(self.row)

    def to_dict(self):
        ret = {}
        for f, id in self.fieldList.iter_fields():
            self.valueList[id].accept(FieldVisitor(), ret)
            # FieldVisitor().toDict(self.valueList[id], ret)
            # if f.startswith('request'):
            #     if 'request' not in ret:
            #         ret['request'] = {}
            #
            #     ret['request'][f[8:]] = self.rowList[id].value
            # else:
            #     ret[f] = self.rowList[id].value
        return ret

    def iter_fields(self, exclude=None, only=None):
        """This method iterates over all fields that are defined and yields
        ``(key, value)`` tuples.  Per default all fields are returned, but
        it's possible to limit that to some fields by providing the `only`
        parameter or to exclude some using the `exclude` parameter.  Both
        should be sets or tuples of field names.
        """
        # if self.type != 'FieldsLine':
        #     return
        goFields = self.row
        if self.fieldList is not None:
            goFields = self.fieldList
        for index, name in enumerate(goFields):
            if (
                    (exclude is only is None)
                    or (exclude is not None and name not in exclude)
                    or (only is not None and name in only)
            ) and name != '':
                try:
                    yield name, index
                    # , getattr(self, name)
                except AttributeError:
                    pass

    def create_record(self, row):
        if self.fieldList is None:
            return

        # 构造行字段
        for index, xfield in enumerate(self.fieldList):
            f = Field(index, row[index], name=xfield)

            if self.valueList is None: self.valueList = []
            self.valueList.append(f)


class RecordVisitor(Visitor):
    def visit(self, element):
        return element.to_dict()